package com.coupons.business.util;

import java.sql.Types;
import java.util.List;
import java.util.Map;

import org.springframework.dao.DataAccessException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcDaoSupport;
import org.springframework.jdbc.support.incrementer.OracleSequenceMaxValueIncrementer;

import com.coupons.business.common.exception.BaseCouponsAppException;


public class BaseUtilDAO extends NamedParameterJdbcDaoSupport implements IBaseUtil{

	

	/**
	 * This method will return the JdbcTemplate
	 *
	 * @return template;
	 */
	public JdbcTemplate getTemplate() {
		JdbcTemplate template = null;
		if (getJdbcTemplate() != null) {
			template = getJdbcTemplate();
		}
		return template;
	}

	/**
	 * This method is used to retrieve the records by passing dynamic parameters
	 *
	 * @param sqlStatement
	 * @param obj
	 * @param rowMap
	 * @return list
	 */
	public List<Object> findRecords(String sqlStatement, Object obj[],
			RowMapper rowMap) throws BaseCouponsAppException {
		if (sqlStatement==null) {
			
			throw new BaseCouponsAppException("SQL is Empty");
		}

		try {
			JdbcTemplate template = getTemplate();
			if (template != null) {
				List<Object> list = template.query(sqlStatement, obj, rowMap);
				return list;
			}
		} catch (Exception e) {			
			throw new BaseCouponsAppException(e);
		}
		return null;
	}

	/**
	 * This method is used to retrieve the records
	 *
	 * @param sqlStatement
	 * @param obj
	 * @param rowMap
	 * @return list
	 */
	public List findRecords(String sqlStatement, RowMapper rowMap)
			throws BaseCouponsAppException {
		if (null==sqlStatement) {
		
			throw new BaseCouponsAppException("Sql statement is Empty.");
		}

		try {
			JdbcTemplate template = getTemplate();
			if (template != null) {
				List list = template.query(sqlStatement, rowMap);
				return list;
			}
		} catch (Exception e) {			
			throw new BaseCouponsAppException(e);
		}
		return null;
	}

	/**
	 * This method either executes the Query
	 *
	 * @param insertUpdateScript
	 * @param obj
	 * @param types
	 * @return int
	 */
	public int saveOrUpdateOrDelete(String insertUpdateScript, Object obj[])
			throws BaseCouponsAppException {
		if (null==insertUpdateScript) {			
			return 0;
		}
		int noOfRowsUpdated = 0;
		try {
			JdbcTemplate template = getTemplate();
			if (template != null) {
				int types[] = getTypes(obj);
				noOfRowsUpdated = template.update(insertUpdateScript, obj,
						types);
			}
			System.out.println("noOfRowsUpdated"+noOfRowsUpdated);
		} catch (Exception e) {
			
			throw new BaseCouponsAppException(e.getMessage(),e);
		}
		return noOfRowsUpdated;
	}

	/**
	 * This method either executes the Query
	 *
	 * @param insertUpdateScript
	 * @param obj
	 * @param types
	 * @return int
	 */
	public int saveOrUpdateOrDelete(String insertUpdateScript, Object obj[],
			int types[]) throws BaseCouponsAppException {
		if (null!=insertUpdateScript) {			
			return 0;
		}
		int noOfRowsUpdated = 0;
		try {
			JdbcTemplate template = getTemplate();
			if (template != null) {
				noOfRowsUpdated = template.update(insertUpdateScript, obj,
						types);
			}
		} catch (Exception e) {
			
			throw new BaseCouponsAppException(e.getMessage());
		}
		return noOfRowsUpdated;
	}

	
	/**
	 * This method is used to get sequence value
	 *
	 * @param sequenceName
	 * @return int sequenceValue
	 * @throws TcmDaoException
	 */
	public int getSequence(String sequenceName) throws BaseCouponsAppException
	{		
		if (null==sequenceName)
		{
			throw new BaseCouponsAppException("sequence Name is null");
		}
		try {
			JdbcTemplate template = getTemplate();
			if (template != null) {
				String seqStmt = "SELECT " + sequenceName
						+ ".nextVal FROM DUAL";
				int sequenceValue = template.queryForInt(seqStmt);
				return sequenceValue;
			}
		} catch (Exception e) {			
			throw new BaseCouponsAppException(e.getMessage());
		}
		return 0;
	}




	/**
	 * This method is used to get the data types array
	 *
	 * @param Object
	 *            Array
	 * @return int[]
	 *
	 */
	private int[] getTypes(Object[] objArr) {
		int types[] = new int[objArr.length];
		Object obj = null;
		if (objArr != null && objArr.length > 0) {
			for (int i = 0; i < objArr.length; i++) {
				obj = objArr[i];
				if (obj != null) {
					if (obj.getClass().getName().equalsIgnoreCase(
							"java.lang.Short")) {
						types[i] = Types.SMALLINT;
					} else if (obj.getClass().getName().equalsIgnoreCase(
							"java.lang.Byte")) {
						types[i] = Types.SMALLINT;
					} else if (obj.getClass().getName().equalsIgnoreCase(
							"java.lang.Integer")) {
						types[i] = Types.INTEGER;
					} else if (obj.getClass().getName().equalsIgnoreCase(
							"java.lang.Long")) {
						types[i] = Types.BIGINT;
					} else if (obj.getClass().getName().equalsIgnoreCase(
							"java.lang.Float")) {
						types[i] = Types.FLOAT;
					} else if (obj.getClass().getName().equalsIgnoreCase(
							"java.lang.Double")) {
						types[i] = Types.DOUBLE;
					} else if (obj.getClass().getName().equalsIgnoreCase(
							"java.lang.String")) {
						types[i] = Types.VARCHAR;
					} else if (obj.getClass().getName().equalsIgnoreCase(
							"java.lang.Character")) {
						types[i] = Types.CHAR;
					} else if (obj.getClass().getName().equalsIgnoreCase(
							"java.lang.Boolean")) {
						types[i] = Types.BOOLEAN;
					} else if (obj.getClass().getName().equalsIgnoreCase(
							"java.util.Date")) {
						types[i] = Types.TIMESTAMP;
					} else if (obj.getClass().getName().equalsIgnoreCase(
							"java.sql.Date")) {
						types[i] = Types.TIMESTAMP;
					} else if (obj.getClass().getName().equalsIgnoreCase(
							"java.sql.Timestamp")) {
						types[i] = Types.TIMESTAMP;
					}
					else {
						types[i] = Types.VARCHAR;
					}
				} else {
					types[i] = Types.VARCHAR;
				}
			}
		}
		return types;
	}

	/**
	 * this method returns next value of sequence by using OracleSequenceMaxValueIncrementer
	 *
	 * @param sequenceName
	 * @return sequence value int
	 * @throws TcmDaoException
	 */
	public int getSequenceNextValue(String sequenceName) throws BaseCouponsAppException {

		if (null==sequenceName) 
		{			
			throw new BaseCouponsAppException("Sequence Name is Empty or null");
		}
		try {
			OracleSequenceMaxValueIncrementer  oracleSeqIncrementer = new OracleSequenceMaxValueIncrementer(
					this.getDataSource(),sequenceName);
			return oracleSeqIncrementer.nextIntValue();
		}catch(Exception ex) {			
			throw new BaseCouponsAppException(ex);
		}
	}

	/**
	 * Retrieves the list of Objects and supports Named Parameters.
	 *
	 * @param sqlStmt
	 * @param inputMap
	 * @param rowMapper
	 * @return java.util.List
	 * @throws Exception
	 */
	public List queryForList(String sqlStmt, Map inputMap, RowMapper rowMapper)throws Exception {
		try
		{
			return getNamedParameterJdbcTemplate().query(sqlStmt, inputMap,	rowMapper);
		}catch (EmptyResultDataAccessException e)
		{
			return null;
		} catch (DataAccessException e)
		{
			
			throw new Exception(e);
		}
	}

	/**
	 * Retrieves the list of Objects and supports Named Parameters.
	 *
	 * @param sqlStmt
	 * @param inputMap
	 * @param elementType
	 * @return java.util.List
	 * @throws Exception
	 */
//	public List queryForList(String sqlStmt, Map inputMap, Class elementType)throws Exception {
//		try
//		{
//			return getNamedParameterJdbcTemplate().queryForList(sqlStmt, inputMap,	elementType);
//		}catch (EmptyResultDataAccessException e)
//		{
//			return null;
//		} catch (DataAccessException e)
//		{
//			
//			throw new Exception(e);
//		}
//	}


	/**
	 * Retrieves the Object and supports Named Parameters.
	 *
	 * @param sqlStmt
	 * @param inputMap
	 * @param elementType
	 * @return java.util.List
	 * @throws Exception
	 */
	public Object queryForObject(String sqlStmt, Map inputMap, Class elementType)throws Exception {
		try {
			return getNamedParameterJdbcTemplate().queryForObject(sqlStmt, inputMap,
				elementType);
		}catch (EmptyResultDataAccessException e) {
			return null;
		} catch (DataAccessException e)
		{
			
			throw new Exception(e);
		}
	}

	/**
	 * Retrieves the Results and Constructs the Object implemented RowMapper and supports Named Parameters.
	 *
	 * @param sqlStmt
	 * @param inputMap
	 * @param elementType
	 * @return java.util.List
	 * @throws Exception
	 */
	public Object queryForObject(String sqlStmt, Map inputMap, RowMapper rowMapper)throws Exception {
		try {
			return getNamedParameterJdbcTemplate().queryForObject(sqlStmt, inputMap,
					rowMapper);
		}catch (EmptyResultDataAccessException e) {
			return null;
		} catch (DataAccessException e)
		{
			
			throw new Exception(e);
		}
	}

	/**
	 * Updates the list objects as Batch and supports Named Parameters.
	 *
	 * @param sql
	 * @param batchPreparedStatementSetter
	 * @return java.util.List
	 * @throws Exception
	 */
	public int[] saveBatch(String sql, BatchPreparedStatementSetter batchPreparedStatementSetter)throws Exception {
		try
		{
			return getJdbcTemplate().batchUpdate(sql, batchPreparedStatementSetter);
		}catch (EmptyResultDataAccessException e)
		{
			return null;
		} catch (DataAccessException e)
		{
			
			throw new Exception(e);
		}
	}
}
